package com.iwhalecloud.bss.kite.cucc.service.inf;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import com.iwhalecloud.bss.kite.cucc.common.callclient.HttpsCallClient;
import org.apache.commons.collections.MapUtils;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.iwhalecloud.bss.kite.common.callclient.service.IOrderQueryService;
import com.iwhalecloud.bss.kite.common.util.JsonUtils;
import com.iwhalecloud.bss.kite.common.util.KiteMapUtils;
import com.iwhalecloud.bss.kite.common.util.KiteStringUtils;
import com.iwhalecloud.bss.kite.cucc.client.api.inf.IInfBcmcServiceBus;
import com.iwhalecloud.bss.kite.cucc.client.dto.pos.KitePosDTO;
import com.iwhalecloud.bss.kite.cucc.common.constant.BcmcCallClientEnum;
import com.iwhalecloud.bss.kite.cucc.service.util.LocalTokenUtil;
import com.ztesoft.bss.common.util.SpringUtil;

/**
 * @ClassName : InfBcmcServiceBus
 * @Description : 调用BCMC服务总线
 * <p>该类的使命是通过业务类传过来的参数返回接口方出参的data部分，接口调用细节对业务类来说是黑盒。</p>
 * <p>接口调用失败则抛出特定异常信息com.iwhalecloud.bss.kite.common.constant.ErrorConsts.INF_INVOKE_EXCEPTION，可传入详细异常信息</p>
 * <p>有特殊情况再特殊处理</p>
 * @Author : XXZ
 * @Date : 2020/12/14 20:36
 */
@Service
@SuppressWarnings("all")
public class InfBcmcServiceBus implements IInfBcmcServiceBus {

    @Override
    public Map<String, Object> orderCenterPathVariable(String requestParam) {
        Map<String, Object> requestMap = JSONObject
            .parseObject(JsonUtils.transKeyToUpperCaseObject(requestParam).toJSONString(), Map.class);
        Map<String, Object> pathVariableReq = new HashMap<>();
        pathVariableReq.put("PATH_VARIABLE_REQ", requestMap);

        String result = HttpsCallClient.postStringWithObject(
            BcmcCallClientEnum.ORDER_CENTER_PATH_VARIABLE.getCenterCode(),
            BcmcCallClientEnum.ORDER_CENTER_PATH_VARIABLE.getServiceCode(), LocalTokenUtil.getParamMap(pathVariableReq),
            LocalTokenUtil.getHeaderMap());
        return JSON.parseObject(result, Map.class);
    }

    @Override
    public Map<String, Object> getWorkOrderInfo(String orderId) {

        Map<String, Object> dataMap = new HashMap<>();
        IOrderQueryService orderQueryService = SpringUtil.getBean(IOrderQueryService.class);

        Map uniBssBody = new HashMap();
        Map getWorksheetInfoReq = new HashMap();
        getWorksheetInfoReq.put("orderId", orderId);
        uniBssBody.put("GET_WORKSHEET_INFO_REQ", getWorksheetInfoReq);
        Map<String, Object> param = LocalTokenUtil.getParamMap(uniBssBody);
        param.put("OP_CODE", "json_jike_orderCenter_getWorksheetInfo");
        String resultStr = HttpsCallClient.postStringWithObject(
            BcmcCallClientEnum.ORDER_CENTER_QUERY_ORDER_DETAIL.getCenterCode(),
            BcmcCallClientEnum.ORDER_CENTER_QUERY_ORDER_DETAIL.getServiceCode(), param, Maps.newHashMap());
        Map result = MapUtils.EMPTY_MAP;
        if (!KiteStringUtils.isEmpty(resultStr)) {
            result = JSON.parseObject(resultStr, Map.class);
        }

        Map uniBssHead = (Map) result.get("UNI_BSS_HEAD");
        // if (KiteMapUtils.isNotEmpty(uniBssHead)) {
        String respDesc = KiteMapUtils.getString(uniBssHead, "RESP_DESC");
        // if (KiteStringUtils.isEqual("Success", respDesc)) {
        Map bodyMap = (Map) result.get("UNI_BSS_BODY");
        Map requestRsp = (Map) bodyMap.get("GET_WORKSHEET_INFO_RSP");
        dataMap = (Map<String, Object>) requestRsp.get("data");
        // }
        // else {
        // ErrorConsts.INF_INVOKE_ERROR.throwOut(CallClientEnum.QRY_WORKORDER_INFO.getServiceCode(), "获取工单信息",
        // "获取工单信息失败");
        // }
        // }
        // else {
        // ErrorConsts.INF_INVOKE_ERROR.throwOut(CallClientEnum.QRY_WORKORDER_INFO.getServiceCode(), "获取工单信息",
        // "获取工单信息失败");
        // }
        return dataMap;

    }

    @Override
    public Map<String, Object> orderCenterUpdatePiece(KitePosDTO posDto, String custId, String orderId) {
        Map<String, Object> uniBssBody = new HashMap<>();
        JSONObject posJSONObject = JsonUtils.parseObject(JSONObject.toJSONString(posDto));
        replaceKey(posJSONObject.get("request"), "aPP_ID", "APP_ID");
        removeKey(posJSONObject.get("accounts"), "acctContractCode", "isCenterDirectSign", "isDefault", "openDate", "provinceAcctId");

        JSONArray accounts = (JSONArray) posJSONObject.get("accounts");
        accounts.forEach(account -> {
            JSONObject accountObject = (JSONObject) account;
            if (KiteStringUtils.isEmpty(KiteMapUtils.getString(accountObject, "custId"))) {
                accountObject.put("custId", custId);
            }
        });

        JSONArray contracts = (JSONArray) posJSONObject.get("contract");
        contracts.forEach(contract -> {
            removeKey(((JSONObject) contract).get("attachments"), "uploadTime");
        });

        JSONArray users = (JSONArray) posJSONObject.get("users");
        users.forEach(user -> {
            JSONObject userObject = (JSONObject) user;
            if (KiteStringUtils.isEmpty(KiteMapUtils.getString(userObject, "useCustInstId"))) {
                userObject.put("useCustInstId", KiteMapUtils.getString(userObject, "instanceId"));
            }
        });

        JSONObject useCustomer = (JSONObject) posJSONObject.get("useCustomer");
        if (Objects.nonNull(useCustomer)) {
            useCustomer.put("isNewCustomer", KiteStringUtils.valueOf(useCustomer.get("isNewCustomer")));
            posJSONObject.put("useCustomer", Arrays.asList(useCustomer));
        }

        JSONObject customer = (JSONObject) posJSONObject.get("customer");
        customer.put("isNewCustomer", KiteStringUtils.valueOf(customer.get("isNewCustomer")));
        if (KiteStringUtils.isNotEmpty(customer.getString("contactPhone")) && customer.getString("contactPhone").length() > 11) {
            removeKey(customer, "contactPhone");
        }

        JSONObject order = (JSONObject) posJSONObject.get("order");
        if (KiteStringUtils.isNotEmpty(order.getString("flowNodeId")) && order.getString("flowNodeId").length() > 32) {
            removeKey(order, "flowNodeId");
        }
        JSONArray goods = (JSONArray) posJSONObject.get("goods");
        goods.forEach(good -> {
            Object count = ((JSONObject) good).get("count");
            ((JSONObject) good).put("count", KiteStringUtils.valueOf(count));
        });

        removeKey(posJSONObject.get("payments"), "deadline");
        JSONArray payments = (JSONArray) posJSONObject.get("payments");
        payments.forEach(payment -> {
            Object amount = ((JSONObject) payment).get("amount");
            ((JSONObject) payment).put("amount", KiteStringUtils.valueOf(amount));

        });

        // removeJSONObjectByKey(posJSONObject, "attrs", "changeType", "endDate", "originValue", "startDate", "type");
        removeJSONObjectByKey(posJSONObject, "attachments", "uploadTime");

        posJSONObject.put("orderId", orderId);
        uniBssBody.put("UPDATE_PIECE_REQ", posJSONObject);
        Map<String, Object> infRequest = new HashMap<>();
        infRequest.put("OP_CODE", "json_jike_orderCenter_UpdatePiece");
        infRequest.put("UNI_BSS_BODY", uniBssBody);
        String result = HttpsCallClient.postStringWithObject(BcmcCallClientEnum.ORDER_CENTER_UPDATE_PIECE, infRequest, LocalTokenUtil.getHeaderMap());
        return JSON.parseObject(result, Map.class);
    }

    private void replaceKey(Object obj, String sourceKey, String targetKey) {
        if (Objects.isNull(obj)) {
            return;
        }
        if (obj instanceof JSONObject) {
            JSONObject jsonObject = (JSONObject) obj;
            Object value = jsonObject.get(sourceKey);
            jsonObject.remove(sourceKey);
            jsonObject.put(targetKey, value);
        }
        if (obj instanceof JSONArray) {
            JSONArray jsonArray = (JSONArray) obj;
            jsonArray.forEach(t -> {
                JSONObject jsonObject = (JSONObject) t;
                Object value = jsonObject.get(sourceKey);
                jsonObject.remove(sourceKey);
                jsonObject.put(targetKey, value);
            });
        }
    }

    private void removeKey(Object obj, String... sourceKeys) {
        if (Objects.isNull(obj)) {
            return;
        }
        if (obj instanceof JSONObject) {
            JSONObject jsonObject = (JSONObject) obj;
            Arrays.asList(sourceKeys).forEach(sourceKey -> {
                jsonObject.remove(sourceKey);
            });
        }
        if (obj instanceof JSONArray) {
            JSONArray jsonArray = (JSONArray) obj;
            jsonArray.forEach(t -> {
                JSONObject jsonObject = (JSONObject) t;
                Arrays.asList(sourceKeys).forEach(sourceKey -> {
                    jsonObject.remove(sourceKey);
                });
            });
        }
    }

    public void removeJSONObjectByKey(JSONObject jsonObject, String outKey, String... removeKeys) {
        if (KiteMapUtils.isEmpty(jsonObject)) {
            return;
        }
        jsonObject.forEach((key, value) -> {
            if (KiteStringUtils.equals(outKey, key)) {
                this.removeKey(value, removeKeys);
            }
            else if (value instanceof JSONObject) {
                removeJSONObjectByKey((JSONObject) value, outKey, removeKeys);
            }
            else if (value instanceof JSONArray) {
                dealRemoveJSONArray((JSONArray) value, outKey, removeKeys);
            }
        });
    }

    private void dealRemoveJSONArray(JSONArray jsonArray, String outKey, String... removeKeys) {
        jsonArray.stream().forEach(jsonObject -> {
            if (jsonObject instanceof JSONObject) {
                removeJSONObjectByKey((JSONObject) jsonObject, outKey, removeKeys);
            }
            else if (jsonObject instanceof JSONArray) {
                dealRemoveJSONArray((JSONArray) jsonObject, outKey, removeKeys);
            }
        });
    }


}
